package com.zr.planclass.service.impl;

import com.zr.planclass.mapper.PlanClassMapper;
import com.zr.planclass.pojo.*;
import com.zr.planclass.service.PlanClassService;
import com.zr.utils.*;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.InputStream;
import java.util.*;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author xiaowei
 * @Date 2019/12/20 11:11
 * @Version 1.0
 */
@Service
public class PlanClassServiceImpl implements PlanClassService {
    @Autowired
    private PlanClassMapper planClassMapper;

    //  计划大类新增
    @Override
    @Transactional
    public ResultVo add(@Valid List<PlanClassAddVo> planClassAddVo) {
        List<String> codeList = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        for (PlanClassAddVo classAddVo : planClassAddVo) {
            codeList.add(classAddVo.getCode());
            nameList.add(classAddVo.getName());

        }
        //根据前端传过来的编码查询数据库，查看是否存在数据！
        List<String> list = planClassMapper.queryByCode(codeList);
        if (list.size() > 0) {
            return ResultBuilderVo.error("编码已经存在！");
        }
        ResultVo yanzheng = yanzheng(nameList);
        if (!yanzheng.getSuccess()) {
            return yanzheng;
        }
        PlanClassVo planClassVo = new PlanClassVo();
        BeanUtils.copyProperties(planClassAddVo, planClassVo);
        Date nowDate = new Date();
        planClassVo.setCreateName("张三");
        planClassVo.setCreateTime(nowDate);
        planClassVo.setUpdateName("张三");
        planClassVo.setUpdateTime(nowDate);
        planClassMapper.addPlanClass(planClassVo);
        return ResultBuilderVo.success();
    }


    @Override
    public ResultVo queryById(Integer id) {
        PlanClassVo planClassVo = planClassMapper.queryById(id);
        if (!planClassVo.getStatus()) {
            planClassVo.setStatusName(StatusEnum.JINYONG.getName());
        }
        if (planClassVo.getStatus()) {
            planClassVo.setStatusName(StatusEnum.QIYONG.getName());
        }
        if (planClassVo == null) {
            return ResultBuilderVo.error(ErrorMessage.OBJECTISNOT);
        }
        return ResultBuilderVo.success(planClassVo);
    }

    @Override
    @Transactional
    public ResultVo update(@Valid PlanClassUpdateVo planClassUpdateVo) {
        //要修改的数据是否存在
        PlanClassVo planClassVo2 = planClassMapper.queryById(planClassUpdateVo.getId());
        if (planClassVo2 == null) {
            return ResultBuilderVo.error("修改对象不存在！");
        }
        List<String> list = new ArrayList<>();
        list.add(planClassUpdateVo.getName());
        //验证名称是否存在
        ResultVo yanzheng = yanzheng(list);
        if (!yanzheng.getSuccess()) {
            return yanzheng;
        }
        PlanClassVo planClassVo = new PlanClassVo();
        BeanUtils.copyProperties(planClassUpdateVo, planClassVo);
        Date nowDate = new Date();
        planClassVo.setUpdateName("张三");
        planClassVo.setUpdateTime(nowDate);
        planClassMapper.updatePlanClass(planClassVo);
        return ResultBuilderVo.success();
    }

    @Override
    @Transactional
    public ResultVo updateStatus(@Valid PlanClassUpdateStatusVo planClassUpdateStatusVo) {
        //修改的数据是否存在
        PlanClassVo planClassVo2 = planClassMapper.queryById(planClassUpdateStatusVo.getId());
        if (planClassVo2 == null) {
            return ResultBuilderVo.error("修改对象不存在！");
        }

        //数据转换
        //修改数据库
        PlanClassVo planClassVo = new PlanClassVo();
        BeanUtils.copyProperties(planClassUpdateStatusVo, planClassVo);
        Date nowDate = new Date();
        planClassVo.setUpdateName("张三");
        planClassVo.setUpdateTime(nowDate);
        planClassMapper.updatePlanClassStatus(planClassVo);
        return ResultBuilderVo.success();
    }

    @Override
    public ResultVo queryPage(PlanClassSelectVo planClassSelectVo) {
        List<PlanClassVo> planClassVoList = planClassMapper.queryPageData(planClassSelectVo);
        if (!CollectionUtils.isEmpty(planClassVoList)) {
            for (PlanClassVo planClassVo : planClassVoList) {
                if (planClassVo.getStatus() != null) {
                    if (!planClassVo.getStatus()) {
                        planClassVo.setStatusName(StatusEnum.JINYONG.getName());
                    }
                    if (planClassVo.getStatus()) {
                        planClassVo.setStatusName(StatusEnum.QIYONG.getName());
                    }
                }

            }
        }
        int count = planClassMapper.queryPageCount(planClassSelectVo);
        AllRecords allRecords = new AllRecords();
        allRecords.setDataList(planClassVoList);
        allRecords.setTotalNumber(count);
        allRecords.setPageIndex(planClassSelectVo.getPageIndex());
        allRecords.setPageSize(planClassSelectVo.getPageSize());
        allRecords.resetTotalNumber(count);
        //3.设置响应参数
        return ResultBuilderVo.success(allRecords);
    }

    public ResultVo yanzheng(List<String> nameList) {
        //根据前端传过来的名称查询数据库，查看是否存在数据！
        List<String> list = planClassMapper.queryByName(nameList);
        if (list.size() > 0) {
            return ResultBuilderVo.error(ErrorMessage.PLANCLASSUPDATENAMEEXIST);
        }

        return ResultBuilderVo.success();
    }

    @Override
    public HashMap<Object, List> getPullDownList() {
        HashMap<Object, List> map = new HashMap<>();
        List<StatusVo> status = new ArrayList<>();
        for (StatusEnum c : StatusEnum.values()) {
            StatusVo statusVo = new StatusVo();
            statusVo.setLabel(c.getName());
            statusVo.setValue(c.getIndex());
            status.add(statusVo);
        }
        map.put("status", status);
        List<StatusVo> statusLists = new ArrayList<>();
        for (InquiryStatusEnum c : InquiryStatusEnum.values()) {
            StatusVo statusVo1 = new StatusVo();
            statusVo1.setLabel(c.getName());
            statusVo1.setValue(c.getIndex());
            statusLists.add(statusVo1);
        }
        map.put("inquiryStatus", statusLists);
        List<StatusVo> inquiryCurrency = new ArrayList<>();
        for (CurrencyCodeEnum c : CurrencyCodeEnum.values()) {
            StatusVo statusVo2 = new StatusVo();
            statusVo2.setLabel(c.getName());
            statusVo2.setValue(c.getIndex());
            inquiryCurrency.add(statusVo2);
        }
        map.put("currencyCode", inquiryCurrency);
        List<StatusVo> isIncludeTax = new ArrayList<>();
        for (IsTaxEnum c : IsTaxEnum.values()) {
            StatusVo statusVo3 = new StatusVo();
            statusVo3.setLabel(c.getName());
            statusVo3.setValue(c.getIndex());
            isIncludeTax.add(statusVo3);
        }
        map.put("isTax", isIncludeTax);
        List<StatusVo> inquiryType = new ArrayList<>();
        for (TypeEnum c : TypeEnum.values()) {
            StatusVo statusVo4 = new StatusVo();
            statusVo4.setLabel(c.getName());
            statusVo4.setValue(c.getIndex());
            inquiryType.add(statusVo4);
        }
        map.put("type", inquiryType);
        return map;
    }

    @Override
    public ResultVo importPlanClass(MultipartFile file) throws Exception {

        //1.给用户导入模板
        //2.提示版本问题，询问产品经理支持哪种版本的导入格式，
        // 使用2007版本的导入模板，根据版本不同，poi导入技术的读取方式不同
        if (!file.getOriginalFilename().contains("xlsx")) {
            return ResultBuilderVo.error(ErrorMessage.VERSIONIS);
        }
        ResultVo<List<PlanClassAddVo>> resultVo = checkVersionAndFormat(file);
        if (!resultVo.getSuccess()) {
            return resultVo;
        }
        ResultVo<List<PlanClassAddVo>> resultVo1 = checkData(resultVo.getData());
        if (!resultVo1.getSuccess()) {
            return resultVo1;
        }
        ResultVo<List<PlanClassAddVo>> resultVo3 = checkCode1(resultVo1.getData());
        if (!resultVo3.getSuccess()) {
            return resultVo3;
        }
        ResultVo<List<PlanClassAddVo>> resultVo4 = checkCode2(resultVo3.getData());
        if (!resultVo4.getSuccess()) {
            return resultVo4;
        }
        List<PlanClassAddVo> planClassAddVoList = new ArrayList<>();
        for (PlanClassAddVo planClassAddVo : resultVo4.getData()) {
            planClassAddVoList.add(planClassAddVo);
        }
        ResultVo add = add(planClassAddVoList);
        if (!add.getSuccess()) {
            return add;
        }
        return ResultBuilderVo.success();
    }

    //导出
    @Override
    public ResultVo exportMater(HttpServletResponse response, String code, String name, Integer status) throws Exception {
        //将数据库中的数据查出来
        PlanClassSelectVo plantSelectVo = new PlanClassSelectVo();
        plantSelectVo.setCode(code);
        plantSelectVo.setName(name);
        plantSelectVo.setStatus(status);
        List<PlanClassVo> planClassVoList = planClassMapper.exportMater(plantSelectVo);
        if (planClassVoList.size() > 10000) {
            return ResultBuilderVo.error(ErrorMessage.ZUODUOTIAOSHU);
        }
        //数据转换
        for (PlanClassVo planClassVo:planClassVoList){
            Integer status1 = planClassVo.getStatus()==true?1:0;
            planClassVo.setStatusName(StatusEnum.getName(status1));
        }
        //把数据写入excel表格中
        //输出到浏览器

        //获取响应输出流
        ServletOutputStream out = response.getOutputStream();
        //给输出文件设置名称
        POIClass.toPackageOs(response, "计划大类导出");
        //读取模板中的数据
        InputStream in = ExportUtil.toPackageIn("templates/计划大类导出模板.xlsx");
        //根据模板的数据、把查询出来的数据给摸版SHeet1组中的数据赋值、把excel输出到浏览器上
        writeDataToExcel(in, "Sheet1", planClassVoList, out);
        if (in != null) {
            in.close();
            out.close();
        }
        return ResultBuilderVo.success();
    }

    // 由于此方法不能通用, 所以单独写在这里
    private void writeDataToExcel(InputStream in, String sheetName,
                                  List<PlanClassVo> resultList, ServletOutputStream out) throws Exception {
        //POi读取模板
        XSSFWorkbook wb = new XSSFWorkbook(in);
        //读取sheet1中的数据
        Sheet sheet = wb.getSheet(sheetName);
        if (sheet != null) {
            //向sheet1中赋值，设置样式
            toResultListValueInfo(sheet, resultList);
        }
        //把数据写入到输出流中
        wb.write(out);
        //关闭poi方法
        wb.close();
    }
    /**
     * 插入excel表中项目信息
     *
     * @param sheet
     */
    private void toResultListValueInfo(Sheet sheet, List<PlanClassVo> plantList) {
        //从第4行开始赋值
        int row_column = 5;
        //遍历数据集合
        for (PlanClassVo obj : plantList) {
            //创建一行的方法
            Row row = sheet.createRow(row_column);
            // 给第一列序号赋值赋值
            POIClass.toCellValue(row,0, obj.getId() + "");
            // 给第二列编码赋值
            POIClass.toCellValue(row, 1, obj.getCode() + "");
            // 给第3列名称赋值
            POIClass.toCellValue(row, 2, obj.getName() + "");
            // 给状态赋值
            POIClass.toCellValue(row, 3, obj.getStatusName() + "");
            //下一行
            row_column++;
        }
    }



    private ResultVo checkCode2(List<PlanClassAddVo> planClassAddVoList) {
        //9.对于需要转换的数据进行数据转换，比如数据库存的数据为数字格式，用户输入的为汉字，需要把汉字转换为数字存储
        for (PlanClassAddVo planClassAddVo : planClassAddVoList) {
            if (StatusEnum.getValue(planClassAddVo.getStatusName()) == null) {
                return ResultBuilderVo.error(ErrorMessage.STATUSISNOT);
            } else {
                Integer status = StatusEnum.getValue(planClassAddVo.getStatusName());
                Boolean booleanStatus = status == 1 ? true : false;
                planClassAddVo.setStatus(booleanStatus);
            }

        }
        return ResultBuilderVo.success(planClassAddVoList);
    }

    private ResultVo checkCode1(List<PlanClassAddVo> planClassAddVoList) {
        //8.验证数据是否重复
        List<String> plassCodeList = new ArrayList<>();
        for (PlanClassAddVo planClassAddVo : planClassAddVoList) {
            plassCodeList.add(planClassAddVo.getCode());
        }
        Set<String> setSpareCode = new HashSet<>(plassCodeList);
        if (plassCodeList.size() != setSpareCode.size()) {
            return ResultBuilderVo.error(ErrorMessage.SPARRISNOTTWO);
        }
        List<String> codeList = new ArrayList<>();
        List<String> chognfuList = new ArrayList<>();
        for (String code : plassCodeList) {
            if (codeList.contains(code)) {
                chognfuList.add(code);
            } else {
                codeList.add(code);
            }
        }
        if (!chognfuList.isEmpty()) {
            return ResultBuilderVo.error(ErrorMessage.SPARRISNOTTWOIS + chognfuList);
        }
        return ResultBuilderVo.success(planClassAddVoList);
    }

    private ResultVo checkData(List<PlanClassAddVo> planClassVoList) {
        //5.验证不为空字段是否为空
        for (PlanClassAddVo planClassAddVo : planClassVoList) {
            if (planClassAddVo.getName().isEmpty()) {
                return ResultBuilderVo.error(ErrorMessage.PLANCLASSADDNAME);
            }
        }
        for (PlanClassAddVo planClassAddVo : planClassVoList) {
            if (planClassAddVo.getCode().isEmpty()) {
                return ResultBuilderVo.error(ErrorMessage.PLANCLASSADDCODE);
            }
        }
        //6.验证字符长度是否符合需求
        for (PlanClassAddVo planClassAddVo : planClassVoList) {
            if (planClassAddVo.getName().length() > 50) {
                return ResultBuilderVo.error(ErrorMessage.PLANCLASSADDNAMELENGTH);
            }
        }
        for (PlanClassAddVo planClassAddVo : planClassVoList) {
            if (planClassAddVo.getCode().length() > 50) {
                return ResultBuilderVo.error(ErrorMessage.PLANCLASSADDCODELENGTH);
            }
        }
        return ResultBuilderVo.success(planClassVoList);
    }

    private ResultVo checkVersionAndFormat(MultipartFile file) throws Exception {
        //3.模板是否是需要导入的模板，验证模板是否正确
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        //获取单元格中的信息
        XSSFSheet sheetAt = workbook.getSheetAt(0);
        //验证第一行第一列是否是 "计划大类导入模板"
        if (!String.valueOf(sheetAt.getRow(sheetAt.getFirstRowNum()).getCell(0)).
                equals("计划大类导入模板")) {
            return ResultBuilderVo.error(ErrorMessage.FORMWORKWRONG);
        }
        //新建集合存放模板数据
        List<PlanClassAddVo> planClassVoList = new ArrayList<>();
        //遍历excel表格中的所有数据，从第五行开始读取，没有数据时终止遍历。
        for (int i = sheetAt.getFirstRowNum() + 4; i <= sheetAt.getLastRowNum(); i++) {
            //读取第一行数据
            XSSFRow row = sheetAt.getRow(i);
            if (row != null) {
                String test1 = String.valueOf(row.getCell(1)).trim();
                String test2 = String.valueOf(row.getCell(2)).trim();
                String test3 = String.valueOf(row.getCell(3)).trim();
                //判断存入的数据不能为''和null
                if (!test1.equals("") && !test1.equals("null")
                        || !test2.equals("") && !test1.equals("null")
                        || !test3.equals("") && !test1.equals("null")) {
                    //把每一行的数据放入到实体类中
                    ResultVo<PlanClassAddVo> inquiryImportVo = build(row);
                    if (!inquiryImportVo.getSuccess()) {
                        return inquiryImportVo;
                    }
                    //把实体类中的数据放入到list集合中
                    planClassVoList.add(inquiryImportVo.getData());
                }
            }
        }
        return ResultBuilderVo.success(planClassVoList);

    }

    private ResultVo<PlanClassAddVo> build(XSSFRow row) {
        PlanClassAddVo planClassAddVo = new PlanClassAddVo();
        //4.格式问题，必须保持统一格式，统一为字符串格式导入
        try {
            planClassAddVo.setCode(String.valueOf(row.getCell(1)));
        } catch (Exception e) {
            return ResultBuilderVo.error(ErrorMessage.PLEASECHECKCODEFORMAT);
        }
        planClassAddVo.setName(String.valueOf(row.getCell(2)));
        planClassAddVo.setStatusName(String.valueOf(row.getCell(3)));
        planClassAddVo.setRemark(String.valueOf(row.getCell(4)));

        return ResultBuilderVo.success(planClassAddVo);
    }

}



